package vistop.ui;

import java.util.Map;
import java.util.TreeMap;

import javax.media.opengl.GL2;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.GLUtessellatorCallback;

/*
 * Tessellator callback implemenation with all the callback routines. You
 * could use GLUtesselatorCallBackAdapter instead. 
 */
public class TessellCallBack implements GLUtessellatorCallback {

	private GL2 gl;
	private GLU glu;

	static Map<Integer,String> typeMap = new TreeMap<Integer, String>();
	static{
		typeMap.put(GL2.GL_POINTS,"GL_POINTS");
		typeMap.put(GL2.GL_LINES,"GL_LINES");
		typeMap.put(GL2.GL_LINE_STRIP,"GL_LINE_STRIP");
		typeMap.put(GL2.GL_LINE_LOOP,"GL_LINE_LOOP");
		typeMap.put(GL2.GL_TRIANGLES,"GL_TRIANGLES");
		typeMap.put(GL2.GL_TRIANGLE_STRIP,"GL_TRIANGLE_STRIP");
		typeMap.put(GL2.GL_TRIANGLE_FAN,"GL_TRIANGLE_FAN");
		typeMap.put(GL2.GL_QUADS,"GL_QUADS");
		typeMap.put(GL2.GL_QUAD_STRIP,"GL_QUAD_STRIP");
		typeMap.put(GL2.GL_POLYGON,"GL_POLYGON");
	}
	
	
	
	public TessellCallBack(GL2 gl, GLU glu)
	{
		this.gl = gl;
		this.glu = glu;
	}

	public void begin(int type)
	{
		//System.out.println(typeMap.get(type));
		gl.glBegin(type);
	}

	public void end()
	{
		gl.glEnd();
	}

	public void vertex(Object vertexData)
	{
		double[] pointer;
		if (vertexData instanceof double[])
		{
			pointer = (double[]) vertexData;
			if (pointer.length == 6) {
				//System.out.println("Color("+pointer[3]+","+pointer[4]+","+pointer[5]+")");
				gl.glColor3dv(pointer, 3);
			}
			gl.glColor3f(1f,1f,1f);
			gl.glVertex3dv(pointer, 0);
		}else{
			throw new Error("vertexData is not double[]");
		}

	}

	public void vertexData(Object vertexData, Object polygonData)
	{
		throw new Error("vertexData must not be called.");
	}

	/*
	 * combineCallback is used to create a new vertex when edges intersect.
	 * coordinate location is trivial to calculate, but weight[4] may be used to
	 * average color, normal, or texture coordinate data. In this program, color
	 * is weighted.
	 */
	public void combine(double[] coords, Object[] data, float[] weight, Object[] outData)
	{
		double[] vertex = new double[6];

		vertex[0] = coords[0];
		vertex[1] = coords[1];
		vertex[2] = coords[2];
		for (int i = 3; i < 6/* 7OutOfBounds from C! */; i++)
			vertex[i] = weight[0] * ((double[]) data[0])[i] 
			          + weight[1] * ((double[]) data[1])[i] 
			          + weight[2] * ((double[]) data[2])[i]
			          + weight[3] * ((double[]) data[3])[i];
		outData[0] = vertex;
	}

	public void combineData(double[] coords, Object[] data, //
			float[] weight, Object[] outData, Object polygonData)
	{
		throw new Error("combineData must not be called.");	
	}

	public void error(int errnum)
	{
		String estring;

		estring = glu.gluErrorString(errnum);
		System.err.println("Tessellation Error: " + estring);
		System.exit(0);
	}

	public void beginData(int type, Object polygonData)
	{
		throw new Error("beginData must not be called.");	
	}

	public void endData(Object polygonData)
	{
		throw new Error("endData must not be called.");	
	}

	public void edgeFlag(boolean boundaryEdge)
	{
		throw new Error("edgeFlag must not be called.");	
	}

	public void edgeFlagData(boolean boundaryEdge, Object polygonData)
	{
		throw new Error("edgeFlagData must not be called.");	
	}

	public void errorData(int errnum, Object polygonData)
	{
		throw new Error("errorData must not be called.");	
	
	}
}// tessellCallBack
